package cn.haocxy.jfm.gui;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
import java.util.function.Predicate;

import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.stage.Window;
import cn.haocxy.jfm.file.Clipboard;
import cn.haocxy.jfm.file.FilePath;
import cn.haocxy.jfm.func.FileFunc;
import cn.haocxy.jfm.func.GUIFunc;

public class FileListPaneMenu {

	private FileListPane currentFileListPane = null;
	
	private ContextMenu menu = new ContextMenu();
	
	private boolean shown = false;
	
	private MenuItem openInNewWindow = new MenuItem("打开新窗口");
	
	private MenuItem sep1 = new SeparatorMenuItem();
	
	private MenuItem newDir = new MenuItem("新建文件夹");
	
	private MenuItem newFile = new MenuItem("新建文件");
	
	private MenuItem paste = new MenuItem("粘贴");
	
	private MenuItem sep2 = new SeparatorMenuItem();
	
	private MenuItem selectAll = new MenuItem("全选");
	
	private MenuItem unselectAll = new MenuItem("全不选");
	
	private MenuItem reverseSelect = new MenuItem("反选");
	
	private FileListPaneMenu() {
		
		menu.setAutoHide(true);
		menu.setHideOnEscape(true);
		
		menu.setOnShowing(e->onShowing());
		menu.setOnShown(e->shown=true);
		menu.setOnHidden(e->shown=false);
		
		menu.getItems().addAll(
				openInNewWindow,
				sep1,
				selectAll,
				unselectAll,
				reverseSelect,
				sep2,
				newDir, 
				newFile, 
				paste
				 
				);
		
		
		openInNewWindow.setOnAction(e->openInNewWindow());
		
		selectAll.setOnAction(e->{
			currentFileListPane.getFileList().selectAll();
		});
		
		unselectAll.setOnAction(e->{
			currentFileListPane.getFileList().unselectAll();
		});
		
		reverseSelect.setOnAction(e->{
			currentFileListPane.getFileList().reverseSelect();
		});
		
		paste.setOnAction(e->paste());
		
		newDir.setOnAction(e->newFolder());
		
		newFile.setOnAction(e->newFile());
	}
	
	private FilePath getCurrentDir() {
		return currentFileListPane.getFileList().getCurrentDir();
	}
	
	private void onShowing() {
		
		FilePath path = getCurrentDir();
		boolean isWritable = path.isWritable();
		boolean isWin32Root = path.isWin32Root();
		
		Clipboard cb = Clipboard.get();
		
		filt(newDir, item->isWritable);
		filt(sep1, item->!isWin32Root);
		filt(newFile, item->isWritable);
		filt(paste, item->isWritable && !cb.isEmpty());
		filt(sep2, item->!isWin32Root);
		filt(selectAll, item->!isWin32Root);
		filt(unselectAll, item->!isWin32Root);
		filt(reverseSelect, item->!isWin32Root);
	}
	
	private void filt(MenuItem item, Predicate<MenuItem> filter) {
		if (item == null || filter == null) {
			return;
		}
		if (filter.test(item)) {
			item.setVisible(true);
		} else {
			item.setVisible(false);
		}
	}
	
	private static FileListPaneMenu obj = null;
	
	public static FileListPaneMenu get() {
		if (obj == null) {
			synchronized (FileListPaneMenu.class) {
				if (obj == null) {
					obj = new FileListPaneMenu();
				}
			}
		}
		return obj;
	}
	
	public boolean shown() {
		return shown;
	}
	
	public void hide() {
		currentFileListPane = null;
		menu.hide();
	}
	
	public void show(FileListPane fileListPane, double x, double y) {
		currentFileListPane = fileListPane;
		menu.show(fileListPane.toNode(), x, y);
	}
	
	private void openInNewWindow() {
		FilePath dir = currentFileListPane.getFileList().getCurrentDir();
		Window w = currentFileListPane.toNode().getScene().getWindow();
		GUIFunc.newJfmWindow(w, dir);
	}

	private void paste() {
		FileFunc.paste(getCurrentDir(), null);
	}

	private void newFolder() {
		Path dir = getCurrentDir().toPath();
		getNewPath(dir, "新建文件夹").toFile().mkdir();
	}
	
	private void newFile() {
		Path dir = getCurrentDir().toPath();
		try {
			getNewPath(dir, "新建文件").toFile().createNewFile();
		} catch (IOException e) {
			currentFileListPane.info(e.getMessage());
		}
	}
	
	private Path getNewPath(Path dir, String base) {
		Path p = dir.resolve(base);
		if (!Files.exists(p)) {
			return p;
		}
		for (int i = 2; i < 100; ++i) {
			p = dir.resolve(base + "(" + i + ")");
			if (!Files.exists(p)) {
				return p;
			}
		}
		return p.resolve(base + "(" + UUID.randomUUID() + ")");
	}
}
